﻿using Deployment.Data.Environment.Connection;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Xml.Serialization;


namespace Deployment.Data.Environment
{
    [XmlRoot("Environment")]
    [Serializable()]
    public class EnvironmentsFile : NotifyPropertyChanged
    {
        private ObservableSortedList<Environment> _Environments = new ObservableSortedList<Environment>(4, new EnvironmentComparer());

        public ObservableSortedList<Environment> Environments
        {
            get { return _Environments; }
        }

        public void AddEnvironment(Environment newEnvironment)
        {
            //check that we aren't duplicating names first
            foreach(Environment env in _Environments)
            {
                if (string.Equals(env.Name, newEnvironment.Name, StringComparison.CurrentCultureIgnoreCase))
                {
                    throw new ArgumentException("An environment with the name of [" + newEnvironment.Name + "] already exists.");
                }
            }
            _Environments.Add(newEnvironment);
        }

        public Environment CloneEnvironment(string existingName, string newName, bool addNow = false)
        {
            Environment existing = get(existingName);
            if (existing == null)
            {
                throw new ArgumentException("Could not locate existing environment with name [" + existingName + "]");   
            }
            //Perform a deep copy, as must as possible
            Environment newEnv = new Environment();
            newEnv.Name = newName;
            foreach (AbstractConnection con in existing.Connections)
            {
                newEnv.AddConnection(con);
            }
            if (addNow)
                AddEnvironment(newEnv);

            return newEnv;
        }
        
        public Environment get(string name)
        {
            foreach (Environment env in _Environments)
            {
                if (string.Equals(env.Name, name, StringComparison.CurrentCultureIgnoreCase))
                {
                    return env;
                }
            }
            return null;
        }

        public bool RemoveEnvironment(Environment env)
        {
            return _Environments.Remove(env);
        }

        public bool RemoveEnvironment(string environmentName)
        {
            Environment env = get(environmentName);
            if (env != null)
                return RemoveEnvironment(env);
            return false;
        }

        public void SaveToFile(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                throw new ArgumentException("fileName cannot be null or empty.");
            using (StreamWriter sw = new StreamWriter(fileName, false))
            {
                XmlSerializer xml = new XmlSerializer(typeof(EnvironmentsFile));
                xml.Serialize(sw, this);
                sw.Close();
            }
        }

        public static EnvironmentsFile LoadFromFile(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                throw new ArgumentException("fileName cannot be null or empty.");
            if (!File.Exists(fileName))
                throw new FileNotFoundException("Unable to locate input file", fileName);
            EnvironmentsFile obj;
            FileStream inStream = new FileStream(fileName, FileMode.Open);
            XmlSerializer xml = new XmlSerializer(typeof(EnvironmentsFile));

            obj = (EnvironmentsFile)xml.Deserialize(inStream);
            inStream.Close();
            return obj;
        }

        private class EnvironmentComparer : IComparer<Environment>
        {

            public int Compare(Environment x, Environment y)
            {
                if (x == null && y == null)
                    return 0;
                if (x == null && y != null)
                    return -1;
                if (x != null && y == null)
                    return 1;

                return string.Compare(x.Name, y.Name, true);
            }
        }
    }
}
